package com.danci.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.danci.common.Result;
import com.danci.common.WordExcel;
import com.danci.dto.LearnRecord;
import com.danci.dto.LearnWordDto;
import com.danci.dto.UserRequest;
import com.danci.dto.WordsDto;
import com.danci.entity.Userinfo;
import com.danci.entity.Words;
import com.danci.mapper.UserinfoMapper;
import com.danci.mapper.WordsMapper;
import com.danci.service.IWordsService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 单词表 服务实现类
 * </p>
 *
 * @author xxx
 * @since 2024-05-13
 */
@Service
@Slf4j
@AllArgsConstructor
public class WordsServiceImpl extends ServiceImpl<WordsMapper, Words> implements IWordsService {

    private final WordsMapper wordsMapper;
    private final UserinfoMapper userinfoMapper;

    @Override
    public void initWords() {

        List<Words> words = new ArrayList<>();

        EasyExcel.read("E:\\IdeaProjects\\myDemo\\danci\\src\\main\\resources\\static\\大学英语六级单词排序版.xls",
                WordExcel.class,
                new ReadListener<WordExcel>() {
                    @Override
                    public void invoke(WordExcel o, AnalysisContext analysisContext) {
                        Words words1 = new Words();
                        BeanUtils.copyProperties(o, words1);
                        words1.setId(IdUtil.fastSimpleUUID());
                        words1.setLid("2222");
                        words.add(words1);
                    }

                    @Override
                    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                        words.forEach(wordsMapper::insert);
                    }
                }).sheet().doRead();
    }

    @Override
    public Result learn(LearnWordDto learnWordDto) {
        LearnRecord learnRecord = new LearnRecord();
        BeanUtils.copyProperties(learnWordDto, learnRecord);
        learnRecord.setId(IdUtil.fastSimpleUUID());
        learnRecord.setLearnTime(new Date());
        wordsMapper.deleteRecord(learnRecord.getUserId(),learnWordDto.getWordId());
        wordsMapper.addLearnRecord(learnRecord);
        return Result.success("新增成功");
    }

    @Override
    public Result recommend(UserRequest userRequest) {
        // 记忆算法 计算需要推送给用户的单词
        // 获取用户每日计划量
        Integer planDay = wordsMapper.getPlanDay(userRequest.getUserId());
        Userinfo userinfo = userinfoMapper.selectById(userRequest.getUserId());
        if (planDay == null || planDay == 0) {
            return Result.success(new ArrayList<>());
        } else {
            List<WordsDto> words = new ArrayList<>();
            List<String> wordIds = new ArrayList<>();
            // 获取需要复习的单词记录
            List<LearnRecord> recordsToReview = new ArrayList<>();
            recordsToReview.addAll(wordsMapper.findLearnRecordsByDateAndType(getPastDate(4), 0, userRequest.getUserId()));
            recordsToReview.addAll(wordsMapper.findLearnRecordsByDateAndType(getPastDate(2), 1, userRequest.getUserId()));
            recordsToReview.addAll(wordsMapper.findLearnRecordsByDateAndType(getPastDate(1), 2, userRequest.getUserId()));
            for (LearnRecord record : recordsToReview) {
                Words word = wordsMapper.selectById(record.getWordId());
                if (word != null) {
                    wordIds.add(word.getId());
                    WordsDto wordsDto = new WordsDto();
                    BeanUtils.copyProperties(word, wordsDto);
                    wordsDto.setType(1);
                    words.add(wordsDto);
                }
            }
            if (userRequest.getType() == 1) {
                return Result.success(words);
            }
            else if (userRequest.getType() == 0) {
                // 判断今天已学习的单词量和每日计划比较 大于等于就不继续学习了
                if (wordsMapper.getRecordLearnCount(userRequest.getUserId()) >= planDay) {
                    return Result.fail("今日已学习数量已满足每日计划,请明天再来或修改每日计划数量");
                }
                words.clear();
                if (userRequest.getType() == 0) {
                    List<Words> newWords = wordsMapper.findNewWords(userinfo.getLid(), wordIds, planDay);
                    newWords.forEach(word -> {
                        WordsDto wordsDto = new WordsDto();
                        BeanUtils.copyProperties(word, wordsDto);
                        wordsDto.setType(0);
                        words.add(wordsDto);
                    });
                }
            }

            return Result.success(words);
        }
    }

    @Override
    public Result importWords(MultipartFile file, String lid) throws IOException {
        List<Words> words = new ArrayList<>();

        EasyExcel.read(file.getInputStream(),
                WordExcel.class,
                new ReadListener<WordExcel>() {
                    @Override
                    public void invoke(WordExcel o, AnalysisContext analysisContext) {
                        Words words1 = new Words();
                        BeanUtils.copyProperties(o, words1);
                        words1.setId(IdUtil.fastSimpleUUID());
                        words1.setLid(lid);
                        words.add(words1);
                    }

                    @Override
                    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                        words.forEach(wordsMapper::insert);
                    }
                }).sheet().doRead();
        return Result.success("导入成功");
    }

    private Date getPastDate(int days) {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, -days);
        return cal.getTime();
    }
}
